/*============================================================================
  File:      caseprocessor.h
 
  Summary:   Declaration of CASEPROCESSOR class that is used to extract
			 data from Analysis Services.
 
  Date:		 June 30, 2004
------------------------------------------------------------------------------
  This file is part of the Microsoft SQL Server Code Samples.
 
  Copyright (C) 2003 Microsoft Corporation.  All rights reserved.
 
This source code is intended only as a supplement to Microsoft
Development Tools and/or on-line documentation.  See these other
materials for detailed information regarding Microsoft code samples.
 
THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
============================================================================*/

#pragma once

#include "stdafx.h"
#include "..\..\dmalgo.h"
#include "DmhVector.h" // Using STL vectors

// CASEPROCESSOR is a helper class that implements the IDMCaseProcessor 
// interface for you. It hides the distinction between dense and sparse 
// representation of the source data; it lets you access each in-coming 
// case using either a sparse "view" or a dense "view", regardless of the
// source representation.
//
// You create a CASEPROCESSOR by calling
//
//	CComObjectDM<CASEPROCESSOR>::CreateInstance()
//
// and then initialize the resulting object via CASEPROCESSOR::Initialize().
// The initialize funtion takes a CASEREADER pointer as one of its arguments; to 
// use the CASEPROCESSOR, you need to create a new class that inherets from 
// CASEREADER and which implements either ProcessCaseSparse() or 
// ProcessCaseDense() - only one of these functions will ever be called; which 
// one is determined by the pure virtual CASEPROCESSOR::Viewtype() implemented by
// your derived reader.
//
// After you obtain the IDMCaseProcessor interface from a call to QueryInterface()
// and pass to IDMPushCaseSet::StartCases(), each call to IDMCaseProcessor::ProcessCase() 
// will be translated by CASEPROCESSOR into a call to one of your CASEREADER handlers.
//
// CASEPROCESSOR uses the data transformations described in "DataValues.h" to 
// convert all values to type double, regardless of the "real" type of the
// variable. It also will implement the missing-at-random tranformation if
// requested upon initialization.
//
// If your reader wants to stop reading cases (for example, your algorithm needs
// only the first 100 cases), the ProcessCase*() function should return S_FALSE.

class CASEREADER : public DMHALLOC
{
  public:

	// Types of data views

	enum VIEWTYPE
	{
		viewtypeDense,
		viewtypeSparse,
	};

	// Return either viewtypeDense or viewtypeSparse in your derived class to
	// determine which ProcessCase*() function will be called by the CASEPROCESSOR.

	virtual VIEWTYPE	Viewtype()	= 0;

	// Over-ride exactly one of these functions in your derived class.

	virtual HRESULT ProcessCaseSparse(ULONG ulID, VINT& viAttribute, VDBL& vdblValue)
	{
		return E_FAIL;
	}

	virtual HRESULT ProcessCaseDense(ULONG ulID, VDBL& vdblValue)
	{
		return E_FAIL;
	}
};

// CASEPROCESSOR

class ATL_NO_VTABLE CASEPROCESSOR : 
	public CComObjectRootEx<CComMultiThreadModel>,
	public IDMCaseProcessor,
	public DMHALLOC
{
  public:

	BEGIN_COM_MAP(CASEPROCESSOR)
		COM_INTERFACE_ENTRY(IDMCaseProcessor)
	END_COM_MAP()

	CASEPROCESSOR();
	
	virtual HRESULT	Initialize(IDMAttributeSet*	pidmattributeset, 
							   IDMPushCaseSet*	pidmpushcaseset, 
							   CASEREADER*		pcasereader,
							   bool				bMissingAtRandom = false);
	
	virtual ~CASEPROCESSOR();

	// IDMCaseProcessor

	STDMETHOD (RequestCapacity)(ULONG in_cCapacity);
	STDMETHOD (ProcessCase)(DM_CaseID dmcaseid, ULONG cValue, ULONG* rgValue);

	ULONG		_cAttribute;	// Number of attributes in the source data 
    
  protected:
	
	// Attributes

	CComPtr<IDMAttributeSet>	_spidmattributeset;

  private:
	
	bool		_bMissingAtRandom;	// Convert state 0 of analysis-services
									// categorical values to be missing, and "shift"
									// the remaining states.
	VB			_vbCategorical;		// [iAttribute]

	bool		_bDensePushSet;		// Is the source data dense?

	CASEREADER*	_pcasereader;
	CASEREADER::VIEWTYPE	_viewtype;

	VDBL		_vdblValue;			// Used for both dense and sparse access
	VINT		_viAttribute;		// Used only for sparse access
};






			